﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Drawing;
using System.Drawing.Drawing2D;

namespace Stone
{
    public class GlobalFunctions
    {
        public static System.Globalization.NumberFormatInfo numberFormat_EnUS = new System.Globalization.CultureInfo("en-US", false).NumberFormat;

        public static double Convert_Knots_to_KilometerPerHour(double knots)
        {
            return knots * 1.852;
        }

        /// <summary>
        /// method to rotate an image either clockwise or counter-clockwise
        /// </summary>
        /// <param name="img">the image to be rotated</param>
        /// <param name="rotationAngle">the angle (in degrees).
        /// NOTE: 
        /// Positive values will rotate clockwise
        /// negative values will rotate counter-clockwise
        /// </param>
        /// <returns></returns>
        public static Image RotateImage(Image img, float rotationAngle)
        {
            //create an empty Bitmap image
            Bitmap bmp = new Bitmap(img.Width, img.Height);

            //turn the Bitmap into a Graphics object
            Graphics gfx = Graphics.FromImage(bmp);

            //now we set the rotation point to the center of our image
            gfx.TranslateTransform((float)bmp.Width / 2, (float)bmp.Height / 2);

            //now rotate the image
            gfx.RotateTransform(rotationAngle);

            gfx.TranslateTransform(-(float)bmp.Width / 2, -(float)bmp.Height / 2);

            //set the InterpolationMode to HighQualityBicubic so to ensure a high
            //quality image once it is transformed to the specified size
            gfx.InterpolationMode = InterpolationMode.HighQualityBicubic;

            //now draw our new image onto the graphics object
            gfx.DrawImage(img, new Point(0, 0));

            //dispose of our Graphics object
            gfx.Dispose();

            //return the image
            return bmp;
        }
        public static ArrayList GetSkinsList()
        {
            ArrayList result = new ArrayList();
            DirectoryInfo di = new DirectoryInfo(Settings.Skins_Path);

            if (di.Exists)
                foreach (DirectoryInfo tmp in di.GetDirectories())
                    result.Add(tmp);

            return result;
        }
        public static bool dblTryParse(string str, out double result)
        {
            try
            {
                result = double.Parse(str, numberFormat_EnUS);
                return true;
            }
            catch
            {
                result = 0;
                return false;
            }
        }
        public static bool intTryParse(string str, out int result)
        {
            try
            {
                result = int.Parse(str, numberFormat_EnUS);
                return true;
            }
            catch
            {
                result = 0;
                return false;
            }
        }
        public static int intTryParse(string str)
        {
            try { return int.Parse(str, numberFormat_EnUS); }
            catch { return 0; }
        }

        public static PointF rotatePoint_old(PointF basePoint, PointF sourcePoint, float rotationAngle)
        {
            float r;
            float theta;
            float offsetX;
            float offsetY;
            float offsetTheta;
            float rotateX;
            float rotateY;
            float rotationRadians;
            PointF retPoint;

            try
            {
                //shift x and y relative to 0,0 origin
                offsetX = (sourcePoint.X + (basePoint.X * -1));
                offsetY = (sourcePoint.Y + (basePoint.Y * -1));
                //convert to radians. take absolute value (necessary for x coord only).
                offsetX = (float)Math.Abs(offsetX * (Math.PI / 180));
                offsetY = (float)offsetY * (float)(Math.PI / 180);
                rotationRadians = (float)rotationAngle * (float)(Math.PI / 180);
                //get distance from origin to source point
                r = (float)Math.Sqrt(Math.Pow(offsetX, 2) + (float)Math.Pow(offsetY, 2));
                //get current angle of orientation
                theta = (float)Math.Atan(offsetY / offsetX);
                // add rotation value to theta to get new angle of orientation
                offsetTheta = theta + rotationRadians;
                //calculate new x coord
                rotateX = (float)r * (float)Math.Cos(offsetTheta);
                //calculate new y coord
                rotateY = (float)r * (float)Math.Sin(offsetTheta);
                //convert new x and y back to decimal degrees
                rotateX = (float)rotateX * (float)(180 / Math.PI);
                rotateY = (float)rotateY * (float)(180 / Math.PI);
                //shift new x and y relative to base point
                rotateX = (rotateX + basePoint.X);
                rotateY = (rotateY + basePoint.Y);
                //return new point
                retPoint = new PointF();
                retPoint.X = rotateX;
                retPoint.Y = rotateY;
                return retPoint;
            }
            catch
            {
                return sourcePoint;
            }
        }

//        public static PointF rotatePoint(PointF originPoint, PointF sourcePoint, float rotationAngle)
//        {
////            Public Function RotatePoint(ByRef pPoint As POINT, ByRef pOrigin As POINT, ByVal Degrees As Single) As POINT

////RotatePoint.X = pOrigin.X + ( Cos(D2R(Degrees)) * (pPoint.X - pOrigin.X) - _
////    Sin(D2R(Degrees)) * (pPoint.Y - pOrigin.Y) )
////RotatePoint.Y = pOrigin.Y + ( Sin(D2R(Degrees)) * (pPoint.X - pOrigin.X) + _
////    Cos(D2R(Degrees)) * (pPoint.Y - pOrigin.Y) )
////End Function
//        }

        


        /// <summary>
        /// Converts GPS position in d"dd.ddd' to decimal degrees ddd.ddddd
        /// </summary>
        /// <param name="DM"></param>
        /// <param name="Dir"></param>
        /// <returns></returns>
        public static double GPSToDecimalDegrees(string DM, string Dir)
        {
            try
            {
                if (DM == "" || Dir == "")
                    return 0.0;

                //Get the fractional part of minutes
                //DM = '5512.45',  Dir='N'
                //DM = '12311.12', Dir='E'

                string t = DM.Substring(DM.IndexOf("."));
                double FM = double.Parse(DM.Substring(DM.IndexOf(".")), GlobalFunctions.numberFormat_EnUS);

                //Get the minutes.
                t = DM.Substring(DM.IndexOf(".") - 2, 2);
                double Min = double.Parse(DM.Substring(DM.IndexOf(".") - 2, 2), GlobalFunctions.numberFormat_EnUS);

                //Degrees
                t = DM.Substring(0, DM.IndexOf(".") - 2);
                double Deg = double.Parse(DM.Substring(0, DM.IndexOf(".") - 2), GlobalFunctions.numberFormat_EnUS);

                if (Dir == "S" || Dir == "W")
                    Deg = -(Deg + (Min + FM) / 60);
                else
                    Deg = Deg + (Min + FM) / 60;

                return Deg;
            }
            catch
            {
                return 0.0;
            }
        }
        /// <summary>
        /// Converts GPS position in d"dd.ddd' to decimal degrees ddd.ddddd
        /// </summary>
        /// <param name="DM"></param>
        /// <param name="Dir"></param>
        /// <returns></returns>
        public static string DecimalDegreesToGPS(double source, bool LatitudeOrLongitude)
        {
            string result = "";

            //  KML:  <coordinates>9.181191 45.469017,0</coordinates>
            //  NMEA: 9° 10' 52.2876"   45° 28' 8.4612"
            //  $GPRMC,144651.506,A,4529.4504,N,00914.1955,E,000.0,128.1,031010,,,A*6C
            //  $GPRMC, 144651.506, A, 4529.4504, N, 00914.1955, E, 000.0, 128.1, 031010, , , A*6C

            //NMEA: (Dm,H) 

            double sourceAbsolute = Math.Abs(source);
            int degrees = (int)sourceAbsolute;
            double minutes = (double)(sourceAbsolute - (double)degrees) * 60;

            string hemisphere = ",";

            if (LatitudeOrLongitude)
            {
                if (source >= 0) hemisphere += "E";
                else hemisphere += "W";
            }
            else
            {
                if (source >= 0) hemisphere += "N";
                else hemisphere += "S";
            }


            result = degrees.ToString() + minutes.ToString("#.#####").Replace(",", ".") + hemisphere;


            return result;
        }

        public static GPSEventType String2Eventtype(string strData)
        {
            if (strData.StartsWith("$" + GPSEventType.GPGGA.ToString()))
                return GPSEventType.GPGGA;
            else if (strData.StartsWith("$" + GPSEventType.GPGLL.ToString()))
                return GPSEventType.GPGLL;
            else if (strData.StartsWith("$" + GPSEventType.GPGSA.ToString()))
                return GPSEventType.GPGSA;
            else if (strData.StartsWith("$" + GPSEventType.GPGSV.ToString()))
                return GPSEventType.GPGSV;
            else if (strData.StartsWith("$" + GPSEventType.GPRMC.ToString()))
                return GPSEventType.GPRMC;
            else if (strData.StartsWith("$" + GPSEventType.PGRME.ToString()))
                return GPSEventType.PGRME;
            else
                return GPSEventType.Unknown;
        }

        public static Bitmap ResizeBitmap(Bitmap b, int nWidth, int nHeight)
        {
            Bitmap result = new Bitmap(nWidth, nHeight);
            using (Graphics g = Graphics.FromImage((Image)result))
                g.DrawImage(b, 0, 0, nWidth, nHeight);
            return result;
        }
        public static string GetFileSizeString(string filePath)
        {
            FileInfo info = new FileInfo(filePath);
            long size = info.Length;
            FileSizeFormatProvider fsfp = new FileSizeFormatProvider();
            string sizeString = size.ToString();
            return sizeString;
        }

        public class FileSizeFormatProvider : IFormatProvider, ICustomFormatter
        {
            public object GetFormat(Type formatType)
            {
                if (formatType == typeof(ICustomFormatter))
                    return this;

                return null;
            }

            private const string fileSizeFormat = "fs";
            private const Decimal OneKiloByte = 1024M;
            private const Decimal OneMegaByte = OneKiloByte * 1024M;
            private const Decimal OneGigaByte = OneMegaByte * 1024M;

            public string Format(string format, object arg, IFormatProvider formatProvider)
            {
                if (format == null || !format.StartsWith(fileSizeFormat))
                    return defaultFormat(format, arg, formatProvider);

                if (arg is string)
                    return defaultFormat(format, arg, formatProvider);

                Decimal size;

                try
                {
                    size = Convert.ToDecimal(arg);
                }
                catch (InvalidCastException)
                {
                    return defaultFormat(format, arg, formatProvider);
                }

                string suffix;
                if (size > OneGigaByte)
                {
                    size /= OneGigaByte;
                    suffix = "GB";
                }
                else if (size > OneMegaByte)
                {
                    size /= OneMegaByte;
                    suffix = "MB";
                }
                else if (size > OneKiloByte)
                {
                    size /= OneKiloByte;
                    suffix = "kB";
                }
                else
                {
                    suffix = " B";
                }

                string precision = format.Substring(2);

                if (String.IsNullOrEmpty(precision))
                    precision = "2";

                return String.Format("{0:N" + precision + "}{1}", size, suffix);

            }

            private static string defaultFormat(string format, object arg, IFormatProvider formatProvider)
            {
                IFormattable formattableArg = arg as IFormattable;

                if (formattableArg != null)
                    return formattableArg.ToString(format, formatProvider);

                return arg.ToString();
            }

        }
    }
}
